<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.18"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>MuPDFCore: MuPDFCore: Multiplatform .NET Core bindings for MuPDF</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="icon.svg"/></td>
  <td id="projectalign" style="padding-left: 0.5em;">
   <div id="projectname">MuPDFCore
   &#160;<span id="projectnumber">1.0.0</span>
   </div>
   <div id="projectbrief">Multiplatform .NET Core bindings for MuPDF</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.18 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
var searchBox = new SearchBox("searchBox", "search",false,'Search');
/* @license-end */
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(function() {
  initMenu('',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
/* @license-end */</script>
<div id="main-nav"></div>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
  <div id="nav-tree">
    <div id="nav-tree-contents">
      <div id="nav-sync" class="sync"></div>
    </div>
  </div>
  <div id="splitbar" style="-moz-user-select:none;" 
       class="ui-resizable-handle">
  </div>
</div>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(document).ready(function(){initNavTree('md__readme.html',''); initResizable(); });
/* @license-end */
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div class="PageDoc"><div class="header">
  <div class="headertitle">
<div class="title"><a class="el" href="namespace_mu_p_d_f_core.html">MuPDFCore</a>: Multiplatform .NET Core bindings for MuPDF </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p><img src="icon.svg" alt="" style="pointer-events: none;" width="256" align="right" class="inline"/></p>
<p><b><a class="el" href="namespace_mu_p_d_f_core.html">MuPDFCore</a></b> is a set of multiplatform .NET Core bindings for <a href="https://mupdf.com/">MuPDF</a>. It can render PDF, XPS, EPUB and other formats to raster images returned either as raw bytes, or as image files in multiple formats (including PNG and PSD). It also supports multithreading.</p>
<p>It also includes <b><a class="el" href="namespace_mu_p_d_f_core_1_1_mu_p_d_f_renderer.html">MuPDFCore.MuPDFRenderer</a></b>, an <a class="el" href="namespace_avalonia.html">Avalonia</a> control to display documents compatible with <a class="el" href="namespace_mu_p_d_f_core.html">MuPDFCore</a> in <a class="el" href="namespace_avalonia.html">Avalonia</a> windows (with multithreaded rendering).</p>
<p>The library is released under the <a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPLv3</a> licence.</p>
<h1><a class="anchor" id="autotoc_md1"></a>
Getting started</h1>
<p>The <a class="el" href="namespace_mu_p_d_f_core.html">MuPDFCore</a> library targets .NET Standard 2.0, thus it can be used in projects that target .NET Standard 2.0+, .NET Core 2.0+, .NET Framework 4.6.1 and possibly others. <a class="el" href="namespace_mu_p_d_f_core.html">MuPDFCore</a> includes a pre-compiled native library, thus projects using it can only run on Windows, macOS and Linux x64 operating systems.</p>
<p>To use the library in your project, you should install the <a href="https://www.nuget.org/packages/MuPDFCore/">MuPDFCore NuGet package</a> and/or the <a href="https://www.nuget.org/packages/MuPDFCore.MuPDFRenderer/">MuPDFCore.PDFRenderer NuGet package</a>.</p>
<h1><a class="anchor" id="autotoc_md2"></a>
Usage</h1>
<h2><a class="anchor" id="autotoc_md3"></a>
Documentation</h2>
<p>Interactive documentation for the library can be accessed from the <a href="https://arklumpus.github.io/MuPDFCore/">documentation website</a>. A <a href="https://arklumpus.github.io/MuPDFCore/MuPDFCore.pdf">PDF reference manual</a> is also available.</p>
<h2><a class="anchor" id="autotoc_md4"></a>
Examples</h2>
<p>The <a href="https://github.com/arklumpus/MuPDFCore/tree/master/Demo">Demo</a> folder in the repository contains some examples of how the library can be used to extract pages from a PDF or XPS document, render them to a raster image, or combine them in a new document</p>
<p>The <a href="https://github.com/arklumpus/MuPDFCore/tree/master/PDFViewerDemo">PDFViewerDemo</a> folder contains a complete (though minimal) example of a PDF viewer program built around the <code><a class="el" href="class_mu_p_d_f_core_1_1_mu_p_d_f_renderer_1_1_p_d_f_renderer.html" title="A control to render PDF documents (and other formats), potentally using multiple threads.">MuPDFCore.MuPDFRenderer.PDFRenderer</a></code> control.</p>
<p>Note that these examples intentionally avoid any error handling code: in a production setting, you should typically make sure that calls to <a class="el" href="namespace_mu_p_d_f_core.html">MuPDFCore</a> library functions are within a <code>try...catch</code> block to handle any resulting <code>MuPDFException</code>s.</p>
<h2><a class="anchor" id="autotoc_md5"></a>
MuPDFCore library</h2>
<p>The first step when using <a class="el" href="namespace_mu_p_d_f_core.html">MuPDFCore</a> is to create a <code><a class="el" href="class_mu_p_d_f_core_1_1_mu_p_d_f_context.html" title="A wrapper around a MuPDF context object, which contains the exception stack and the resource cache st...">MuPDFCore.MuPDFContext</a></code> object that is used internally by the MuPDF library to store various things:</p>
<div class="fragment"><div class="line">MuPDFContext context = new MuPDFContext();</div>
</div><!-- fragment --><p>This object is <code>IDisposable</code>, therefore you should always call the <code>Dispose()</code> method on it once you are done with it (or, better yet, wrap it in a <code>using</code> directive). In most instances, you will only need one instance of <code>MuPDFContext</code> for your whole application.</p>
<p>Amongst other things, MuPDF uses this context to store a cache of "assets" (e.g. images or fonts) that have been used while rendering documents and that may be needed in future. This requires some memory: by default, the maximum size of this cache store is 256MB; however, if you want to restrict how much memory can be used, you can alter this by providing a <code>long</code> value to constructor, indicating the size in bites for the store. A value of <code>0</code> means that the store can grow up to an unlimited size. Furthermore, you can clear the cache completely by using the <code>MuPDFContext.ClearCache</code> method, or partially by using the <code>MuPDFContext.ShrinkCache</code> method.</p>
<p>Once you have obtained a <code>MuPDFContext</code>, you can use it to open a <code>MuPDFDocument</code>. A document can be opened from a file on disk:</p>
<div class="fragment"><div class="line">MuPDFDocument document = new MuPDFDocument(context, &quot;path/to/file&quot;);</div>
</div><!-- fragment --><p>Or from a <code>byte[]</code> array (in this case, you will have to specify the format of the document):</p>
<div class="fragment"><div class="line">byte[] data;</div>
<div class="line"> </div>
<div class="line">...</div>
<div class="line"> </div>
<div class="line">MuPDFDocument document = new MuPDFDocument(context, data, InputFileTypes.PDF);</div>
</div><!-- fragment --><p>Or from a <code>MemoryStream</code> (in this case too, you will have to specify the format of the document):</p>
<div class="fragment"><div class="line">MemoryStream stream;</div>
<div class="line"> </div>
<div class="line">...</div>
<div class="line"> </div>
<div class="line">MuPDFDocument document = new MuPDFDocument(context, ref stream, InputFileTypes.PDF);</div>
</div><!-- fragment --><p>The <code>MemoryStream</code> is passed with the <code>ref</code> keyword to indicate that the <code>MuPDFDocument</code> will take care of appropriately disposing it once it finishes using it.</p>
<p>A <code>MuPDFDocument</code> is also <code>IDisposable</code> and should be properly disposed of to avoid memory leaks.</p>
<p><b>Important note</b>: the constructor taking a <code>byte[]</code> and the one taking a <code>MemoryStream</code> will not copy the data bytes before sending them to the native MuPDF library functions. Rather, they will <em>pin them in place</em>. This is a <b>bad thing</b> because it will mess up with the Garbage Collector's management of memory. Therefore, this is only suitable for short-lived objects. If you need to initialise a long-lived document object from memory, you should first copy the data to unmanaged memory and then use one of the constructors that take an <code>IntPtr</code> parameter, e.g.:</p>
<div class="fragment"><div class="line">byte[] data;</div>
<div class="line"> </div>
<div class="line">...</div>
<div class="line"> </div>
<div class="line">//Allocate enough unmanaged memory</div>
<div class="line">IntPtr ptr = Marshal.AllocHGlobal(data.Length);</div>
<div class="line"> </div>
<div class="line">//Copy the byte array to unmanaged memory</div>
<div class="line">Marshal.Copy(data, 0, ptr, data.Length);</div>
<div class="line"> </div>
<div class="line">//Wrap the pointer in an IDisposable</div>
<div class="line">IDisposable dispIntPtr = new DisposableIntPtr(ptr);</div>
<div class="line"> </div>
<div class="line">//Create the document</div>
<div class="line">MuPDFDocument document = new MuPDFDocument(ctx, ptr, data.Length, InputFileTypes.PDF, ref dispIntPtr);</div>
</div><!-- fragment --><p>The <code>DisposableIntPtr</code> class is a wrapper around a pointer that calls <code>Marshal.FreeHGlobal</code> on it once it is disposed. Passing it as the final optional parameter of <code>MuPDFDocument</code> constructor (again by reference, to indicate that the document takes ownership of the object) makes sure that the memory is properly freed once the document is disposed.</p>
<p>After having obtained a document, you can do many things with it: for example, you can render a page and save the results to a file on disk, or you can collect multiple pages and combine them in a new document. Code to do this can be found in the <a href="https://github.com/arklumpus/MuPDFCore/blob/master/Demo/Program.cs"><code>Program.cs</code></a> file of the Demo project.</p>
<p>Furthermore, you can render a page directly to memory:</p>
<div class="fragment"><div class="line">byte[] pixelData = document.Render(0, 1, PixelFormats.RGBA);</div>
</div><!-- fragment --><p>This method renders page 0 (i.e. the first page of the document) at a 1x resolution (1pt in the document is equivalent to 1px in the image), preserving alpha (transparency) information, and returns the image as an array of the bytes that constitute the pixel data (four bytes per pixel). A variation of this method allows you to supply a rectangular region of the page that you would like to render, rather than the whole page.</p>
<p>Alternatively, if you already know where the image data should be put (e.g. because you are using some kind of graphics library that lets you manipulate the pixel data of its images), you can use the methods that take an <code>IntPtr</code> destination:</p>
<div class="fragment"><div class="line">IntPtr destination;</div>
<div class="line"> </div>
<div class="line">...</div>
<div class="line"> </div>
<div class="line">document.Render(0, 1, PixelFormats.RGBA, destination);</div>
</div><!-- fragment --><p>In this case, <b>you have to make sure that there is enough memory to hold the resulting image</b>! Otherwise, an <code>AccessViolationException</code> will occur and your program will usually fail catastrophically. Since it may sometimes be hard to determine how much memory a particular image will need (especially because of subtle differences in the rounding routines, which can cause images to be 1px larger or shorter than expected), the <code>GetRenderedSize</code> method is provided, which returns the number of bytes that will be needed to render a certain page. For example:</p>
<div class="fragment"><div class="line">//Get the number of bytes that will be necessary to hold the rendered page at the given resolution.</div>
<div class="line">int sizeInBytes = document.GetRenderedSize(0, 1, PixelFormats.RGBA);</div>
<div class="line"> </div>
<div class="line">//Allocate an appropriate amount of memory.</div>
<div class="line">IntPtr destination = Marshal.AllocHGlobal(sizeInBytes);</div>
<div class="line"> </div>
<div class="line">//Again, we use a DisposableIntPtr to make sure that we are freeing the memory when we are done with it.</div>
<div class="line">using (DisposableIntPtr holder = new DisposableIntPtr(destination))</div>
<div class="line">{</div>
<div class="line">    //Make sure that all the parameters match those of the call to GetRenderedSize, or the size of the</div>
<div class="line">    //resulting image may be different than expected! Even a translation of 1px could have catastrophic</div>
<div class="line">    //consequences.</div>
<div class="line">    document.Render(0, 1, PixelFormats.RGBA, destination);</div>
<div class="line">}</div>
</div><!-- fragment --><p>Finally, <b>none of these methods are inherently thread-safe</b>! E.g. you cannot render multiple pages of the same document (nor multiple regions of a single page) by simply performing multiple calls to <code>MuPDFDocument.Render</code> in parallel. For multi-threaded operation, you must instead use a <code>MuPDFMultiThreadedPageRender</code>. You can obtain one from a document:</p>
<div class="fragment"><div class="line">MuPDFMultiThreadedPageRenderer renderer = document.GetMultiThreadedRenderer(0, 2);</div>
</div><!-- fragment --><p>This method obtains an object that can be used to render the first page of the document using two threads. By using the <code>Render</code> method of this object, the page can be rendered. The page will be rendered to a number of separate tiles equal to the number of threads, which will then be your responsibility to appropriately "stitch up" (e.g. if you want to display them on screen, you could just place them appropriately). The size of each tile (and the position it should occupy) can be computed by using the <code>Split</code> method of the <code>RoundedSize</code> struct.</p>
<p>Furthermore, multiple <code>MuPDFMultiThreadedPageRenderer</code>s can be used in parallel, which makes it possible e.g. to render every page in the document at the same time (while also using multiple threads to render each page). The following example will render all the pages in a document at the same time in RGBA format at a 1.5x zoom, using 2 threads for each page:</p>
<div class="fragment"><div class="line">//Create a MuPDFContext with a using statement, so that it gets disposed at the right time.</div>
<div class="line">using MuPDFContext context = new MuPDFContext();</div>
<div class="line"> </div>
<div class="line">//Open the document also with a using statement.</div>
<div class="line">using MuPDFDocument document = new MuPDFDocument(context, &quot;path/to/file.pdf&quot;);</div>
<div class="line"> </div>
<div class="line">//Create arrays to hold the objects for the various pages</div>
<div class="line"> </div>
<div class="line">//Renderers: one per page</div>
<div class="line">MuPDFMultiThreadedPageRenderer[] renderers = new MuPDFMultiThreadedPageRenderer[document.Pages.Count];</div>
<div class="line"> </div>
<div class="line">//Page size: one per page</div>
<div class="line">RoundedSize[] renderedPageSizes = new RoundedSize[document.Pages.Count];</div>
<div class="line"> </div>
<div class="line">//Boundaries of the tiles that make up each page: one array per page, with one element per thread</div>
<div class="line">RoundedRectangle[][] tileBounds = new RoundedRectangle[document.Pages.Count][];</div>
<div class="line"> </div>
<div class="line">//Addresses of the memory areas where the image data of the tiles will be stored: one array per page, with one element per thread</div>
<div class="line">IntPtr[][] destinations = new IntPtr[document.Pages.Count][];</div>
<div class="line"> </div>
<div class="line">//Cycle through the pages in the document to initialise everything</div>
<div class="line">for (int i = 0; i &lt; document.Pages.Count; i++)</div>
<div class="line">{</div>
<div class="line">    //Initialise the renderer for the current page, using two threads (total number of threads: number of pages x 2</div>
<div class="line">    renderers[i] = document.GetMultiThreadedRenderer(i, 2);</div>
<div class="line"> </div>
<div class="line">    //Determine the boundaries of the page when it is rendered with a 1.5x zoom factor</div>
<div class="line">    RoundedRectangle roundedBounds = document.Pages[i].Bounds.Round(1.5);</div>
<div class="line">    renderedPageSizes[i] = new RoundedSize(roundedBounds.Width, roundedBounds.Height);</div>
<div class="line"> </div>
<div class="line">    //Determine the boundaries of each tile by splitting the total size of the page by the number of threads.</div>
<div class="line">    tileBounds[i] = renderedPageSizes[i].Split(renderers[i].ThreadCount);</div>
<div class="line"> </div>
<div class="line">    destinations[i] = new IntPtr[renderers[i].ThreadCount];</div>
<div class="line">    for (int j = 0; j &lt; renderers[i].ThreadCount; j++)</div>
<div class="line">    {</div>
<div class="line">        //Allocate the required memory for the j-th tile of the i-th page.</div>
<div class="line">        //Since we will be rendering with a 24-bit-per-pixel format, the required memory in bytes is height x width x 3.</div>
<div class="line">        destinations[i][j] = Marshal.AllocHGlobal(tileBounds[i][j].Height * tileBounds[i][j].Width * 3);</div>
<div class="line">    }</div>
<div class="line">}</div>
<div class="line"> </div>
<div class="line">//Start the actual rendering operations in parallel.</div>
<div class="line">Parallel.For(0, document.Pages.Count, i =&gt;</div>
<div class="line">{</div>
<div class="line">    renderers[i].Render(renderedPageSizes[i], document.Pages[i].Bounds, destinations[i], PixelFormats.RGB);</div>
<div class="line">});</div>
<div class="line"> </div>
<div class="line"> </div>
<div class="line">//The code in this for-loop is not really part of MuPDFCore - it just shows an example of using SixLabors.ImageSharp to &quot;stitch&quot; the tiles up and produce the full image.</div>
<div class="line">for (int i = 0; i &lt; document.Pages.Count; i++)</div>
<div class="line">{</div>
<div class="line">    //Create a new (empty) image to hold the whole page.</div>
<div class="line">    SixLabors.ImageSharp.Image renderedPage = new SixLabors.ImageSharp.Image&lt;SixLabors.ImageSharp.PixelFormats.Rgb24&gt;(renderedPageSizes[i].Width, renderedPageSizes[i].Height);</div>
<div class="line"> </div>
<div class="line">    //Draw each tile onto the image.</div>
<div class="line">    for (int j = 0; j &lt; renderers[i].ThreadCount; j++)</div>
<div class="line">    {</div>
<div class="line">        ReadOnlySpan&lt;byte&gt; imageData;</div>
<div class="line"> </div>
<div class="line">        //By using unsafe code, we can avoid having to marshal the image data around.</div>
<div class="line">        unsafe</div>
<div class="line">        {</div>
<div class="line">            //Create a new ReadOnlySpan that reads the unmanaged memory where the image data is located.</div>
<div class="line">            imageData = new ReadOnlySpan&lt;byte&gt;((void*)destinations[i][j], tileBounds[i][j].Height * tileBounds[i][j].Width * 3);</div>
<div class="line">            </div>
<div class="line">        }</div>
<div class="line"> </div>
<div class="line">        //Load the image data in the tile by using the ReadOnlySpan.</div>
<div class="line">        SixLabors.ImageSharp.Image tile = SixLabors.ImageSharp.Image.LoadPixelData&lt;SixLabors.ImageSharp.PixelFormats.Rgb24&gt;(imageData, tileBounds[i][j].Width, tileBounds[i][j].Height);</div>
<div class="line"> </div>
<div class="line">        //Draw the tile on the main image page.</div>
<div class="line">        renderedPage.Mutate(x =&gt; x.DrawImage(tile, new SixLabors.ImageSharp.Point(tileBounds[i][j].X0, tileBounds[i][j].Y0), 1));</div>
<div class="line"> </div>
<div class="line">        //Release the resources held by the tile.</div>
<div class="line">        tile.Dispose();</div>
<div class="line">    }</div>
<div class="line"> </div>
<div class="line">    //Save the full page as a JPG image.</div>
<div class="line">    using (FileStream fs = new FileStream(&quot;page&quot; + i.ToString() + &quot;.jpg&quot;, FileMode.Create))</div>
<div class="line">    {</div>
<div class="line">        renderedPage.SaveAsJpeg(fs);</div>
<div class="line">    }</div>
<div class="line"> </div>
<div class="line">    //Release the resources held by the image.</div>
<div class="line">    renderedPage.Dispose();</div>
<div class="line">}</div>
<div class="line"> </div>
<div class="line"> </div>
<div class="line">//Clean-up code.</div>
<div class="line">for (int i = 0; i &lt; document.Pages.Count; i++)</div>
<div class="line">{</div>
<div class="line">    //Release the allocated memory.</div>
<div class="line">    for (int j = 0; j &lt; renderers[i].ThreadCount; j++)</div>
<div class="line">    {</div>
<div class="line">        Marshal.FreeHGlobal(destinations[i][j]);</div>
<div class="line">    }</div>
<div class="line"> </div>
<div class="line">    //Release the renderer (if you skip this, the quiescent renderer&#39;s threads will not be stopped, and your application will never exit!</div>
<div class="line">    renderers[i].Dispose();</div>
<div class="line">}</div>
</div><!-- fragment --><h2><a class="anchor" id="autotoc_md6"></a>
MuPDFCore.MuPDFRenderer control</h2>
<p>To use the <code>PDFRenderer</code> control in an <a class="el" href="namespace_avalonia.html">Avalonia</a> application, first of all you need to add it to you <a class="el" href="namespace_avalonia.html">Avalonia</a> <code>Window</code>, e.g. in the XAML:</p>
<div class="fragment"><div class="line">&lt;<span class="keywordtype">Window</span> <span class="keyword">xmlns</span>=<span class="stringliteral">&quot;https://github.com/avaloniaui&quot;</span></div>
<div class="line">        ...</div>
<div class="line">        <span class="keyword">xmlns:mupdf</span>=<span class="stringliteral">&quot;clr-namespace:MuPDFCore.MuPDFRenderer;assembly=MuPDFCore.MuPDFRenderer&quot;</span></div>
<div class="line">        <span class="keyword">Opened</span>=<span class="stringliteral">&quot;WindowOpened&quot;</span></div>
<div class="line">        ... &gt;</div>
<div class="line">    &lt;<span class="keywordtype">mupdf:PDFRenderer</span> <span class="keyword">Name</span>=<span class="stringliteral">&quot;MuPDFRenderer&quot;</span> /&gt;</div>
<div class="line">&lt;/<span class="keywordtype">Window</span>&gt;</div>
</div><!-- fragment --><p>You then need to initialise it from the backing code, e.g. in a <code>WindowOpened</code> event:</p>
<div class="fragment"><div class="line">private void WindowOpened(object sender, EventArgs e)</div>
<div class="line">{</div>
<div class="line">    this.FindControl&lt;PDFRenderer&gt;(&quot;MuPDFRenderer&quot;).Initialize(&quot;path/to/file.pdf&quot;);</div>
<div class="line">}</div>
</div><!-- fragment --><p>This way, the renderer will start showing the first page of the specified document, using a number of rendering threads that is decided based on the number of processors in the computer. There are many other ways to initialise a PDFRenderer, so make sure to look at the <a href="https://arklumpus.github.io/MuPDFCore/">documentation</a> to see the other possibilities!</p>
<h1><a class="anchor" id="autotoc_md7"></a>
Building from source</h1>
<p>Building the <a class="el" href="namespace_mu_p_d_f_core.html">MuPDFCore</a> library from source requires the following steps:</p>
<ol type="1">
<li>Building the <code>libmupdf</code> native library</li>
<li>Building the <code>MuPDFWrapper</code> native library</li>
<li>Creating the <code><a class="el" href="namespace_mu_p_d_f_core.html">MuPDFCore</a></code> library NuGet package</li>
</ol>
<p>Steps 1 and 2 need to be performed on all of Windows, macOS and Linux (no cross-compiling)! Otherwise, some native assets will be missing and it will not be possible to build the NuGet package.</p>
<h2><a class="anchor" id="autotoc_md8"></a>
1. Building libmupdf</h2>
<p>You can download the open-source (GNU AGPL) MuPDF source code from <a href="https://mupdf.com/downloads/index.html">here</a>. You will need to uncompress the source file and compile the library on Windows, macOS and Linux. You need the following files:</p>
<ul>
<li>From Windows:<ul>
<li>libmupdf.lib</li>
<li>libthirdparty.lib</li>
</ul>
</li>
<li>From macOS:<ul>
<li>libmupdf.a</li>
<li>libmupdf-third.a</li>
</ul>
</li>
<li>From Linux:<ul>
<li>libmupdf.a</li>
<li>libmupdf-third.a</li>
</ul>
</li>
</ul>
<p>Note that the files from macOS and Linux are different, despite sharing the same name.</p>
<p>Depending on your system, on Linux and/or macOS you may need to enable the <code>-fPIC</code> compiler option to generate library files that can be included in the MuPDFWrapper shared library, otherwise a later step may fail. You can do this in multiple ways, e.g. by opening the <code>Makefile</code> included in the MuPDF source and adding <code>-fPIC</code> at the end of the line specifying <code>CFLAGS</code> (line 23 in the MuPDF 1.17.0 source).</p>
<p>For convenience, these compiled files for MuPDF 1.17.0 are included in the <a href="https://github.com/arklumpus/MuPDFCore/tree/master/native/MuPDFWrapper/lib"><code>native/MuPDFWrapper/lib</code> folder</a> of this repository.</p>
<h2><a class="anchor" id="autotoc_md9"></a>
2. Building MuPDFWrapper</h2>
<p>Once you have the required static library files, you should download the <a class="el" href="namespace_mu_p_d_f_core.html">MuPDFCore</a> source code: <a href="https://github.com/arklumpus/MuPDFCore/archive/v1.0.0.tar.gz">MuPDFCore-1.0.0.tar.gz</a> (or clone the repository) and place the library files in the appropriate subdirectories in the <code>native/MuPDFWrapper/lib/</code> folder.</p>
<p>To compile <code>MuPDFWrapper</code> you will need <a href="https://cmake.org/">CMake</a> and (on Windows) <a href="https://ninja-build.org/">Ninja</a>.</p>
<p>On Windows, the easiest way to get all the required tools is probably to install <a href="https://visualstudio.microsoft.com/it/">Visual Studio</a>. By selecting the "Desktop development with C++" you should get everything you need.</p>
<p>On macOS, you will need to install at least the Command-Line Tools for Xcode (if necessary, you should be prompted to do this while you perform the following steps) and CMake.</p>
<p>Once you have everything at the ready, you will have to build MuPDFWrapper on the three platforms.</p>
<h3><a class="anchor" id="autotoc_md10"></a>
Windows</h3>
<ol type="1">
<li>Assuming you have installed Visual Studio, you should open the "__x64__ Native Tools Command Prompt for VS" (you should be able to find this in the Start menu). Take care to open the x64 version, otherwise you will not be able to compile the library. A normal command propmpt will not work, either.</li>
<li><code>CD</code> to the directory where you have downloaded the <a class="el" href="namespace_mu_p_d_f_core.html">MuPDFCore</a> source code.</li>
<li><code>CD</code> into the <code>native</code> directory.</li>
<li>Type <code>build</code>. This will start the <code>build.cmd</code> batch script that will delete any previous build and compile the library.</li>
</ol>
<p>After this finishes, you should find a file named <code>MuPDFWrapper.dll</code> in the <code>native/out/build/win-x64/MuPDFWrapper/</code> directory. Leave it there.</p>
<h3><a class="anchor" id="autotoc_md11"></a>
macOS and Linux</h3>
<ol type="1">
<li>Assuming you have everything ready, open a terminal in the folder where you have downloaded the <a class="el" href="namespace_mu_p_d_f_core.html">MuPDFCore</a> source code.</li>
<li><code>cd</code> into the <code>native</code> directory.</li>
<li>Type <code>chmod +x build.sh</code>.</li>
<li>Type <code>./build.sh</code>. This will delete any previous build and compile the library.</li>
</ol>
<p>After this finishes, you should find a file named <code>libMuPDFWrapper.dylib</code> in the <code>native/out/build/mac-x64/MuPDFWrapper/</code> directory (on macOS) and a file named <code>libMuPDFWrapper.so</code> in the <code>native/out/build/linux-x64/MuPDFWrapper/</code> directory (on Linux). Leave it there.</p>
<h2><a class="anchor" id="autotoc_md12"></a>
3. Creating the MuPDFCore NuGet package</h2>
<p>Once you have the <code>MuPDFWrapper.dll</code>, <code>libMuPDFWrapper.dylib</code> and <code>libMuPDFWrapper.so</code> files, make sure they are in the correct folders (<code>native/out/build/xxx-x64/MuPDFWrapper/</code>), <b>all on the same machine</b>.</p>
<p>To create the <a class="el" href="namespace_mu_p_d_f_core.html">MuPDFCore</a> NuGet package, you will need the <a href="https://dotnet.microsoft.com/download/dotnet/current">.NET Core 2.0 SDK or higher</a> for your platform. Once you have installed it and have everything ready, open a terminal in the folder where you have downloaded the <a class="el" href="namespace_mu_p_d_f_core.html">MuPDFCore</a> source code and type:</p>
<div class="fragment"><div class="line">cd MuPDFCore</div>
<div class="line">dotnet pack -c Release</div>
</div><!-- fragment --><p>This will create a NuGet package in <code>MuPDFCore/bin/Release</code>. You can install this package on your projects by adding a local NuGet source. </p>
</div></div><!-- contents -->
</div><!-- PageDoc -->
</div><!-- doc-content -->
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
  <ul>
    <li class="footer">Generated by
    <a href="http://www.doxygen.org/index.html">
    <img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.8.18 </li>
  </ul>
</div>
</body>
</html>
